1use super::RealTimeData;
2use bitfields::bitfield;
3use num_enum::{IntoPrimitive, TryFromPrimitive};
4use std::ffi::{c_char, CStr};
5
6#[derive(Debug, Copy, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct GroupData {
9 pub squad_markers: [[f32; 3]; 8],
11
12 pub group_type: Result<GroupType, u32>,
14
15 pub group_member_count: u32,
17}
18
19impl GroupData {
20 pub unsafe fn read(data: *const RealTimeData) -> Self {
25 Self {
26 squad_markers: (*data).squad_markers,
27 group_type: (*data).group_type.try_into(),
28 group_member_count: (*data).group_member_count,
29 }
30 }
31}
32
33#[derive(
34 Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive, IntoPrimitive,
35)]
36#[num_enum(error_type(name = u32, constructor = From::from))]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38#[cfg_attr(
39 feature = "strum",
40 derive(
41 strum::AsRefStr,
42 strum::Display,
43 strum::EnumCount,
44 strum::EnumIter,
45 strum::IntoStaticStr,
46 strum::VariantArray,
47 strum::VariantNames
48 )
49)]
50#[repr(u32)]
51pub enum GroupType {
52 None,
53 Party,
54 RaidSquad,
55 Squad,
56}
57
58#[derive(Debug, Clone)]
63#[repr(C)]
64pub struct GroupMember {
65 account_name: [c_char; 140],
67
68 character_name: [c_char; 140],
70
71 pub subgroup: u32,
76
77 pub profession: u32,
81
82 pub elite_specialization: u32,
86
87 flags: GroupMemberFlags,
89}
90
91impl GroupMember {
92 #[inline]
94 pub fn to_owned(&self) -> GroupMemberOwned {
95 self.into()
96 }
97
98 #[inline]
100 pub const fn account_name_ptr(&self) -> *const c_char {
101 self.account_name.as_ptr()
102 }
103
104 #[inline]
106 pub fn account_name_cstr(&self) -> &CStr {
107 unsafe { CStr::from_ptr(self.account_name.as_ptr()) }
108 }
109
110 #[inline]
112 pub fn account_name(&self) -> String {
113 self.account_name_cstr().to_string_lossy().into_owned()
114 }
115
116 #[inline]
118 pub const fn character_name_ptr(&self) -> *const c_char {
119 self.character_name.as_ptr()
120 }
121
122 #[inline]
124 pub fn character_name_cstr(&self) -> &CStr {
125 unsafe { CStr::from_ptr(self.character_name.as_ptr()) }
126 }
127
128 #[inline]
130 pub fn character_name(&self) -> String {
131 self.character_name_cstr().to_string_lossy().into_owned()
132 }
133
134 #[inline]
136 pub const fn flags(&self) -> GroupMemberFlags {
137 self.flags
138 }
139
140 #[inline]
142 pub const fn is_self(&self) -> bool {
143 self.flags.is_self()
144 }
145
146 #[inline]
148 pub const fn is_in_instance(&self) -> bool {
149 self.flags.is_in_instance()
150 }
151
152 #[inline]
154 pub const fn is_commander(&self) -> bool {
155 self.flags.is_commander()
156 }
157
158 #[inline]
160 pub const fn is_lieutenant(&self) -> bool {
161 self.flags.is_lieutenant()
162 }
163}
164
165#[bitfield(u32)]
166#[derive(Copy, Clone, PartialEq, Eq)]
167#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
168pub struct GroupMemberFlags {
169 pub is_self: bool,
170 pub is_in_instance: bool,
171 pub is_commander: bool,
172 pub is_lieutenant: bool,
173
174 #[bits(28)]
175 _padding: u32,
176}
177
178#[derive(Debug, Clone)]
180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
181pub struct GroupMemberOwned {
182 pub account_name: String,
184
185 pub character_name: String,
187
188 pub subgroup: u32,
190
191 pub profession: u32,
193
194 pub elite_specialization: u32,
196
197 pub is_self: bool,
199
200 pub is_in_instance: bool,
202
203 pub is_commander: bool,
205
206 pub is_lieutenant: bool,
208}
209
210impl From<&GroupMember> for GroupMemberOwned {
211 fn from(member: &GroupMember) -> Self {
212 Self {
213 account_name: member.account_name(),
214 character_name: member.character_name(),
215 subgroup: member.subgroup,
216 profession: member.profession,
217 elite_specialization: member.elite_specialization,
218 is_self: member.is_self(),
219 is_in_instance: member.is_in_instance(),
220 is_commander: member.is_commander(),
221 is_lieutenant: member.is_lieutenant(),
222 }
223 }
224}